package com.dingwen.frame.web.exception;

import com.dingwen.frame.constant.EResultCode;
import com.dingwen.frame.constant.ITipAndMessage;
import com.dingwen.frame.vo.Result;
import com.dingwen.frame.vo.ResultGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Path;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 全局异常处理
 *
 * @author dingwen
 * @date 2021.06.29 10:18
 */
@ControllerAdvice
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 方法参数校验异常处理
     *
     * @param e e
     */
    @ExceptionHandler
    public Result exceptionHandler(MethodArgumentNotValidException e) {
        Map<String, String> errInfoMap = e.getBindingResult().getFieldErrors()
                .stream().collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));
        log.error(ITipAndMessage.METHOD_PARAM_EX + ": {}", errInfoMap);
        return ResultGenerator.genFailureResult(ITipAndMessage.METHOD_PARAM_EX, EResultCode.BAD_REQUEST);
    }


    /**
     * validation 异常处理
     *
     * @param e e
     * @return {@link Result}
     */
    @ExceptionHandler
    public Result exceptionHandler(ConstraintViolationException e) {
        Map<Path, String> errInfoMap = e.getConstraintViolations()
                .stream()
                .collect(Collectors.toMap(ConstraintViolation::getPropertyPath, ConstraintViolation::getMessage));
        log.error(ITipAndMessage.METHOD_PARAM_EX + ": {}", errInfoMap);
        return ResultGenerator.genFailureResult(ITipAndMessage.METHOD_PARAM_EX, EResultCode.BAD_REQUEST);
    }


    /**
     * 异常处理程序
     *
     * @param e e
     * @return {@link Result}
     */
    @ExceptionHandler
    public Result exceptionHandler(Exception e) {
        log.error(ITipAndMessage.SYSTEM_ERR + ": {}", e.getMessage());
        if (e instanceof BindException || e instanceof MissingServletRequestParameterException) {
            return ResultGenerator.genFailureResult(ITipAndMessage.METHOD_PARAM_EX, EResultCode.BAD_REQUEST);
        }
        return ResultGenerator.genFailureResult(ITipAndMessage.SYSTEM_ERR, EResultCode.INTERNAL_SERVER_ERROR);
    }


}
